from common_import import *
from sklearn.cluster import DBSCAN
import mapping
import describe


def cal_price():
    data = tool.get_np("2x.csv")
    unique_dates = np.unique(data["date"])

    average_prices = []

    for date in unique_dates:
        # 按日期筛选数据
        date_mask = data["date"] == date
        data_for_date = data[date_mask]
        # 获取该日期内所有的商品代码
        unique_codes = np.unique(data_for_date["code"])
        for code in unique_codes:
            # 按商品代码筛选数据
            code_mask = data_for_date["code"] == code
            filtered_data = data_for_date[code_mask]
            quantities = filtered_data["quantity"]
            prices = filtered_data["price"]
            avg_price = np.round(np.average(prices, weights=quantities), 2)
            # 计算平均价格并保留两位小数
            average_prices.append((date, code, avg_price))

    average_prices_array = np.array(
        average_prices, dtype=[("date", "U10"), ("code", "i4"), ("average_price", "f4")]
    )

    return average_prices_array


def merge_price():
    sales_data = tool.get_np("sale_price.csv")
    cost_data = tool.get_np("3x.csv")
    new_dtype = [
        ("date", "U10"),
        ("code", "i4"),
        ("sale_price", "f4"),
        ("costprice", "f4"),
    ]
    new_data = np.zeros(sales_data.shape, dtype=new_dtype)

    # 填充新数组的原始销售数据
    new_data["date"] = sales_data["date"]
    new_data["code"] = sales_data["code"]
    new_data["sale_price"] = sales_data["sale_price"]

    # 初始化成本价为NaN（或者可以使用其他填充值）
    new_data["costprice"] = np.nan

    # 将成本数据合并到新数组中
    for entry in cost_data:
        mask = (new_data["date"] == entry["date"]) & (new_data["code"] == entry["code"])
        new_data["costprice"][mask] = entry["costprice"]

    return new_data


def merge_price_quantity():
    price_data = tool.get_np("price.csv")
    quantity_data = tool.get_np("product_daily_quantity.csv")
    new_dtype = [
        ("date", "U10"),
        ("code", "i4"),
        ("sale_price", "f4"),
        ("cost_price", "f4"),
        ("total_quantity", "f4"),
    ]
    new_data = np.zeros(price_data.shape, dtype=new_dtype)

    # 填充新数组的原始价格数据
    new_data["date"] = price_data["date"]
    new_data["code"] = price_data["code"]
    new_data["sale_price"] = price_data["sale_price"]
    new_data["cost_price"] = price_data["cost_price"]

    # 初始化数量为NaN（或者可以使用其他填充值）
    new_data["total_quantity"] = np.nan

    # 将数量数据合并到新数组中
    for entry in quantity_data:
        mask = (new_data["date"] == entry["date"]) & (new_data["code"] == entry["code"])
        new_data["total_quantity"][mask] = entry["total_quantity"]

    return new_data


from sklearn.ensemble import IsolationForest


def remove_outliers(my_data, contamination=0.001):
    data = my_data["addition"]
    data_reshaped = data.reshape(-1, 1)
    # 应用 Isolation Forest 算法
    isolation_forest = IsolationForest(contamination=contamination, random_state=42)
    labels = isolation_forest.fit_predict(data_reshaped)
    # Isolation Forest 将异常点标记为 -1，我们将这些点视为异常点
    filtered_data = my_data[labels != -1]
    print(my_data[labels == -1])
    return filtered_data


def generate_normal_pricecsv():
    data = tool.get_np("price_quantity.csv")
    cost_price = data["cost_price"]
    sale_price = data["sale_price"]
    result = (sale_price - cost_price) / cost_price
    dtype = data.dtype.descr + [("addition", "f8")]
    new_array = np.empty(len(data), dtype=dtype)
    for field in data.dtype.names:
        new_array[field] = data[field]
    new_array["addition"] = result
    return remove_outliers(new_array)


def process_data():
    # 创建一个字典用于存储每个类别的数据
    data = tool.get_np("price_quantity.csv")
    category_data = {i: [] for i in range(1, 7)}
    unique_dates = np.unique(data["date"])
    for date in unique_dates:
        for category in range(1, 7):
            # 筛选出当前日期和当前类别的数据
            mask = (data["date"] == date) & (
                np.array([mapping.get_type(code) for code in data["code"]]) == category
            )
            filtered_data = data[mask]
            if len(filtered_data) > 0:
                # 计算每天的总销售量
                total_quantity_sum = np.sum(filtered_data["total_quantity"])

                # 计算售价指数和成本价指数（加权平均）
                sale_price_index = np.average(
                    filtered_data["sale_price"], weights=filtered_data["total_quantity"]
                )
                cost_price_index = np.average(
                    filtered_data["cost_price"], weights=filtered_data["total_quantity"]
                )

                # 将结果存储到对应的类别数据中
                category_data[category].append(
                    (date, total_quantity_sum, sale_price_index, cost_price_index)
                )

    # 将每个类别的数据转换为结构化数组
    for category in category_data:
        category_data[category] = np.array(
            category_data[category],
            dtype=[
                ("date", "U10"),
                ("total_quantity", "f4"),
                ("sale_price_index", "f4"),
                ("cost_price_index", "f4"),
            ],
        )
    return category_data


def calculate_discount_rates(arr):

    # Calculate discount rate for each transaction
    discount_rates = []
    total_quantity_discounted = 0
    total_quantity_full_price = 0

    for code in np.unique(arr["code"]):
        # Filter transactions for current code
        mask = arr["code"] == code
        transactions = arr[mask]

        total_quantity = np.sum(transactions["quantity"])
        total_sales = np.sum(transactions["quantity"] * transactions["price"])

        # Calculate weighted average discount rate
        weighted_discount_rate = (
            np.sum(
                transactions["quantity"]
                * transactions["price"]
                * transactions["discounted"]
            )
            / total_sales
        )

        # Calculate discount sales percentage
        quantity_discounted = np.sum(
            transactions["quantity"][transactions["discounted"] == 1]
        )
        total_quantity_discounted += quantity_discounted
        quantity_full_price = total_quantity - quantity_discounted
        total_quantity_full_price += quantity_full_price

        if total_quantity_full_price > 0:
            discount_sales_percentage = quantity_discounted / total_quantity_full_price
        else:
            discount_sales_percentage = 0

        discount_rates.append((code, weighted_discount_rate, discount_sales_percentage))

    # Convert discount_rates list to numpy structured array
    dtype_rates = [
        ("code", int),
        ("average_discount_rate", float),
        ("average_discount_sales_rate", float),
    ]
    discount_rates_arr = np.array(discount_rates, dtype=dtype_rates)

    return discount_rates_arr


def calculate_weighted_discount(structured_data):
    # 计算每类商品的加权平均折扣率
    type_discounts = {}

    for date in np.unique(structured_data["date"]):
        daily_data = structured_data[structured_data["date"] == date]

        # 计算当日每种商品的最高价格
        daily_max_prices = {}
        for code in np.unique(daily_data["code"]):
            daily_max_prices[code] = daily_data[daily_data["code"] == code][
                "price"
            ].max()

        # 计算每种商品的折扣率
        for row in daily_data:
            code = row["code"]
            type_ = mapping.get_type(code)

            if row["discounted"] == 1:
                discount_rate = (
                    daily_max_prices[code] - row["price"]
                ) / daily_max_prices[code]
            else:
                discount_rate = 0
                continue

            if type_ not in type_discounts:
                type_discounts[type_] = {
                    "total_weighted_discount": 0,
                    "total_quantity": 0,
                }

            # 加权计算
            type_discounts[type_]["total_weighted_discount"] += (
                discount_rate * row["quantity"]
            )
            type_discounts[type_]["total_quantity"] += row["quantity"]

    # 计算加权平均折扣率
    results = []
    for type_, values in type_discounts.items():
        weighted_discount = (
            values["total_weighted_discount"] / values["total_quantity"]
            if values["total_quantity"] != 0
            else 0
        )
        mytype = mapping.get_typename(type_)
        results.append((mytype, weighted_discount))

    # 转换为结构化数组
    result_dtype = [("type", "U10"), ("discount", float)]
    result_array = np.array(results, dtype=result_dtype)
    result_array["discount"] = 1 - result_array["discount"]
    return result_array


if __name__ == "__main__":
    result = calculate_weighted_discount(tool.get_np("2x.csv"))
    tool.get_csv(result, "discount_type.csv")
    print(result)
